#include "structEdgesBase.hpp"
#include "uniEdges.hpp"
#include "rectEdges.hpp"
#include "structEdges.hpp"
#include "meshTypes.hpp"
#include "util.hpp"

namespace hms
{

#define SHEAD(RETURN_TYPE) \
template<typename EdgesType> \
RETURN_TYPE StructEdgesBase<EdgesType>::

SHEAD()
StructEdgesBase( const StructMeshBase<MeshType>& mesh ) :
	EdgesBase<EdgesType>(mesh)
{}

#ifdef STRUCTMESH_PRECALC_EDGE_PARENT_CELLS
SHEAD(auto) cellsImp(Index order) const -> const Array2Xi& {
	assert(order >= 1);
	return m_cells[order-1];
}
#endif

SHEAD(void) storeIndices(){
	#ifdef STRUCTMESH_PRECALC_EDGE_PARENT_CELLS
	Index ne { this->mesh().nEdges() };

	// m_cells.fill({}); // deleting possibly existing entries
	/* allocate memory */
	for ( int i{0}; i<maxOrder; ++i ){
		m_cells[i].resize(2, ne);
	}

	assert( !omp_in_parallel() );

	OMP_PRAGMA(parallel)
	{
		auto [edgeBeg, edgeLen] = ompSegment(ne);
		Index edgeEnd { edgeBeg + edgeLen - 1 };
		auto edgeIndices { ArrayXi::LinSpaced(edgeLen, edgeBeg, edgeEnd) };
	
		for ( int i{0}; i<maxOrder; ++i ){
			m_cells[i].middleCols(edgeBeg, edgeLen) =
				parentCells( this->mesh(), edgeIndices, i+1 );
		}
	}

	// auto edgeIndices { ArrayXi::LinSpaced(ne, 0, ne-1) };

	// for ( int i{0}; i<maxOrder; ++i ){
	// 	m_cells[i] = std::move( parentCells( this->mesh(), edgeIndices, i+1) );
	// }
	#endif
}


#undef SHEAD

template class StructEdgesBase<UniEdges>;
template class StructEdgesBase<RectEdges>;
template class StructEdgesBase<StructEdges>;

} // namespace hms
